package util;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;
import pojo.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class PostAutoUtil {

    private static ConfigPoJo configPoJo;

    static {
        try {
            configPoJo = ConfigUtil.getConfig();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static List<ServiceDesc> run(Map<String, Set<RequestPoJo>> paramMap, List<RequestDetailPoJo> requestDetailPoJoList) throws Exception {
        // 读取excel的全部接口描述
        List<ServiceDesc> list = CodeExcelUtil.file2List(ConfigUtil.class.getResourceAsStream(configPoJo.getSysInterfaceExcelPath()), ServiceDesc.class);
        // 执行统计结果集合
        List<ServiceDesc> resultList = new ArrayList<>();
        // 遍历并填充采集到的参数进行测试
        Set<RequestPoJo> set = null;
        List<PostResult> calcList = null;
        int postCount = 0;
        PostResult postResult = null;
        for (ServiceDesc desc : list) {
            calcList = new ArrayList<>();
            set = paramMap.get(desc.getServiceCode().trim());
            if (CollectionUtils.isEmpty(set)) {
                continue;
            }
            postCount = 0;
            for (RequestPoJo request : set) {
                // 每个接口编号最大执行次数
                if (postCount >= configPoJo.getExampleMax()) {
                    break;
                }
                System.out.println(DateUtil.now() + "  --  " + desc.getFirstUrl());
                postResult = post(desc, request);
                calcList.add(postResult);
                postCount++;
            }
            // 统计次数
            calcCount(desc, calcList, requestDetailPoJoList);
            desc.setFirstUrl(configPoJo.getSysIp() + desc.getFirstUrl());
            resultList.add(desc);
        }

        return resultList;
    }

    /**
     * 计算成功次数，失败次数，平均耗时等
     *
     * @param desc
     * @param calcList
     * @param requestDetailPoJoList
     */
    public static void calcCount(ServiceDesc desc, List<PostResult> calcList, List<RequestDetailPoJo> requestDetailPoJoList) {
        int failCount = 0;
        int successCount = 0;
        int errorCount = 0;
        long maxTime = 0;
        long minTime = 0;
        long avgTime = 0;

        int filterTotal = 0;

        for (PostResult result : calcList) {
            // 添加到执行明细
            if ("y".equals(configPoJo.getFilterTimeOut())) {
                String ResultType = result.getResultType();
                boolean notFilter = !"FAIL".equals(ResultType) || ("FAIL".equals(ResultType) && "9".equals(ResultType));
                if (notFilter) {
                    requestDetailPoJoList.add(RequestDetailPoJo.build(desc, result));
                }
            } else {
                requestDetailPoJoList.add(RequestDetailPoJo.build(desc, result));
            }
            // 统计各类型执行次数
            if ("SUCCESS".equals(result.getResultType())) {
                if (configPoJo.getPostmanNumber() > successCount) {
                    PostManUtil.addPostManItem(desc, result);
                }
                successCount++;
            } else if ("FAIL".equals(result.getResultType())) {
                // 过滤超时和校验失败
                if ("y".equals(configPoJo.getFilterTimeOut()) && !"9".equals(result.getErrorCode())) {
                    filterTotal++;
                } else {
                    failCount++;
                }
                if (configPoJo.getPostmanNumber() > failCount) {
                    PostManUtil.addPostManItem(desc, result);
                }
            } else {
                if (configPoJo.getPostmanNumber() > errorCount) {
                    PostManUtil.addPostManItem(desc, result);
                }
                errorCount++;
            }
            if (minTime == 0 && maxTime == 0) {
                minTime = result.getTime();
                maxTime = result.getTime();
            }
            if (maxTime < result.getTime()) {
                maxTime = result.getTime();
            } else if (minTime > result.getTime()) {
                minTime = result.getTime();
            }
            avgTime += result.getTime();
        }
        if (avgTime != 0) {
            if ((calcList.size() - filterTotal) != 0) {
                avgTime = (avgTime - filterTotal) / (calcList.size() - filterTotal);
            }
        }
        desc.setAvg(avgTime);
        desc.setMax(maxTime);
        desc.setMin(minTime);
        desc.setSuccess(successCount);
        desc.setFail(failCount);
        desc.setError(errorCount);
        desc.setTotal(calcList.size() - filterTotal);
    }


    public static PostResult post(ServiceDesc serviceDesc, RequestPoJo requestPoJo) {
        PostResult postResult = new PostResult();
        String result = null;
        try {
            long startTime = System.currentTimeMillis();
            String path = serviceDesc.getFirstUrl().startsWith("/") ? serviceDesc.getFirstUrl() : "/" + serviceDesc.getFirstUrl();
            postResult.setUrl(configPoJo.getSysIp() + path);
            // 过滤空值
            JSONFormatUtil.removeEmpty(requestPoJo.getJson());
            postResult.setRequest(requestPoJo.getJson().toJSONString());

            result = HttpUtil.post(postResult.getUrl(), postResult.getRequest());

            postResult.setTime(System.currentTimeMillis() - startTime);
            JSONObject json = JSONObject.parseObject(result);

            if (json.containsKey("transactionStatus")) {
                boolean success = "0".equals(json.getJSONObject("transactionStatus").getString("errorCode"));
                if (success) {
                    postResult.setResultType("SUCCESS");
                } else {
                    postResult.setResultType("FAIL");
                    postResult.setErrorCode(json.getJSONObject("transactionStatus").getString("errorCode"));
                }
            } else {
                postResult.setResultType("ERROR");
            }
            postResult.setResult(json.toJSONString());
        } catch (Throwable e) {
            postResult.setResult(result);
            postResult.setResultType("ERROR");
        }
        return postResult;
    }


}
